home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / a_utils / yacc / occam.lha / occam / occamlex.c < prev    next >
C/C++ Source or Header  |  1989-08-22  |  9KB  |  473 lines

  1. /*
  2.  *    OCCAM lexical analysis routine
  3.  *
  4.  *    pjmp    HRC    31/7/86
  5.  *
  6.  */
  7.  
  8. /*
  9.  * This work is in the public domain.
  10.  * It was written by Peter Polkinghorne in 1986 & 1989 at
  11.  * GEC Hirst Research Centre, Wembley, England.
  12.  * No liability is accepted or warranty given by the Author,
  13.  * still less my employers.
  14.  */
  15.  
  16. /* revision history
  17.  
  18.     0.0    first release                    pjmp    31/7/86
  19.     0.1    make yylex more rational - common exit        pjmp    1/8/86
  20.     0.2    add in comma differentiation - for proc decl    pjmp    4/8/86
  21.  
  22. end revisions */
  23.  
  24. #include <stdio.h>
  25. #include <ctype.h>
  26. #include "lex.h"
  27.  
  28. #define    MAXLINE    256
  29.  
  30. #define    TRUE    1
  31. #define    FALSE    0
  32.  
  33. /************************************************************************/
  34. /* reserved word list - ordered for binary chomp */
  35.  
  36. static struct reserv { char * word; int tok, len; } rlist[] = {
  37.         "AFTER",    COMPOP,    5,
  38.         "ALT",        ALT,    3,
  39.         "AND",        BOOLOP,    3,
  40.         "ANY",        ANY,    3,
  41.         "BYTE",        BYTE,    4,
  42.         "CHAN",        CHAN,    4,
  43.         "DEF",        DEF,    3,
  44.         "FALSE",    BOOL,    5,
  45.         "FOR",        FOR,    3,
  46.         "IF",        IF,    2,
  47.         "NOT",        NOT,    3,
  48.         "NOW",        NOW,    3,
  49.         "OR",        BOOLOP,    2,
  50.         "PAR",        PAR,    3,
  51.         "PROC",        PROC,    4,
  52.         "SEQ",        SEQ,    3,
  53.         "SKIP",        SKIP,    4,
  54.         "TABLE",    TABLE,    5,
  55.         "TRUE",        BOOL,    5,
  56.         "VALUE",    VALUE,    5,
  57.         "VAR",        VAR,    3,
  58.         "WAIT",        WAIT,    4,
  59.         "WHILE",    WHILE,    5,
  60.         0,        0,    0
  61.  
  62.     };
  63.  
  64. /************************************************************************/
  65.  
  66. static    char    line[MAXLINE];    /* where we store the input, line as a time */
  67.  
  68. char    yytext[MAXLINE];    /* where we store text associated with token */
  69.  
  70. int    yylineno=1,        /* line number of input */
  71.     yylen;            /* amount of text stored */
  72.  
  73. static    int    llen,        /* how much in line */
  74.         curind,        /* current indentation */
  75.         indent=0;    /* this lines indent */
  76.         ldebug = TRUE,    /* set to TRUE for debug */
  77.         index;        /* where we are in the line */
  78.  
  79. /* state we are in: either start - get new input, decide what next
  80.             ind - processing indentation
  81.             rest - processing some occam stmt
  82.             eof - tidy up processing
  83. */
  84.  
  85. static    enum    lexstate { Start, Ind, Rest, Eof } state = Start;
  86.  
  87. /************************************************************************/
  88.  
  89. yylex()
  90. /* this function returns the next token (defined by lex.h), a character
  91. value or 0 for end of input. The tokens are defined by standard input
  92. */
  93. {
  94.     int    tok = -1,    /* token to return - init to impossible value */
  95.         sind = index;    /* start of input being processed */
  96.  
  97. /* go round and round until token to return */
  98.     while ( tok < 0  ) {
  99.  
  100. /* decide by state */
  101.     switch (state) {
  102.  
  103.         case Start: {
  104. /*grab some more line */
  105.             if ( fgets( line, MAXLINE-1, stdin ) == NULL ) {
  106.                 state = Eof;
  107.                 break;
  108.  
  109.             } else if ( (llen=strlen(line)) >= MAXLINE-1 ) {
  110.                 fprintf( stderr,
  111.                     "line <%s> longer than %d\n",
  112.                     line, MAXLINE-1 );
  113.                 exit( 1 );
  114.             }/*if*/
  115.  
  116.             index = 0;
  117.             sind = 0;
  118.             indent = 0;
  119.  
  120.  
  121. /* if blank line OR has just comment skip, otherwise got to appropriate state */
  122.  
  123.             if ( m_nulline() ) {
  124.                 /* do nowt */
  125.  
  126.             } else if ( line[0]==' ' && line[1]==' ' ) {
  127.                 state = Ind;
  128.  
  129.             } else {
  130.                 state = Rest;
  131.  
  132.             }/*if*/
  133.  
  134.         break;}/*Start*/
  135.  
  136.         case Ind: {
  137. /* work out indentation */
  138.             if ( line[index]==' ' && line[index+1]==' ' ) {
  139.                 indent++;
  140.                 index+=2;
  141.                 sind+=2;
  142.             } else {
  143.                 state = Rest;
  144.             
  145.             }/*if*/
  146.     
  147.         break;}/*Ind*/
  148.  
  149.         case Rest: {
  150. /* do we have some indentation to adjust for ... */
  151.             if ( curind > indent ) {
  152.                 curind--;
  153.                 tok = END;
  154.                 break;
  155.  
  156.             } else if ( curind < indent ) {
  157.                 curind++;
  158.                 tok = BEG;
  159.                 break;
  160.  
  161.             }/*if*/
  162.  
  163. /* process ch as appropriate */
  164.             switch ( line[index] ) {
  165.  
  166. /* space ignored */
  167.                 case ' ': {
  168.                     sind++;
  169.                     index++;
  170.                 break;}
  171.  
  172. /* eol change state again */
  173.                 case '\n': {
  174.                     yylineno++;
  175.                     index++;
  176.                     state = Start;
  177.                     tok = EOL;
  178.                 break;}
  179.  
  180. /* - a comment perhaps OR just itself */
  181.                 case '-': {
  182.                     if ( line[index+1] == '-' ) {
  183.                         index = llen+1;
  184.                         state = Start;
  185.                         tok = EOL;
  186.  
  187.                     } else {
  188.                         tok = line[index++];
  189.  
  190.                     }/*if*/
  191.                 break;}
  192.  
  193.                 case '<': {
  194.                     if ( line[index+1] == '<' ) {
  195.                         index+=2;
  196.                         tok = SHIFTOP;
  197.  
  198.                     } else {
  199.                         if ( line[index+1] == '=' ||
  200.                             line[index+1] == '>' ) {
  201.                             index++;
  202.                         }/*if*/
  203.                         index++;
  204.                         tok = COMPOP;
  205.                     }/*if*/
  206.                 break;}
  207.  
  208.                 case '>': {
  209.                     if ( line[index+1] == '>' ) {
  210.                         index+=2;
  211.                         tok = SHIFTOP;
  212.  
  213.                     } else if ( line[index+1] == '<' ) {
  214.                         index+=2;
  215.                         tok = LOGOP;
  216.  
  217.                     } else {
  218.                         if ( line[index+1] == '=' ) {
  219.                             index++;
  220.                         }/*if*/
  221.                         index++;
  222.                         tok = COMPOP;
  223.                     }/*if*/
  224.  
  225.                 break;}
  226.  
  227.                 case '/': {
  228.                     if ( line[index+1] == '\\' ) {
  229.                         index+=2;
  230.                         tok = LOGOP;
  231.  
  232.                     } else {
  233.                         tok = line[index++];
  234.  
  235.                     }/*if*/
  236.                 break;}
  237.  
  238.                 case '\\': {
  239.                     if ( line[index+1] == '/' ) {
  240.                         index+=2;
  241.                         tok = LOGOP;
  242.  
  243.                     } else {
  244.                         tok = line[index++];
  245.  
  246.                     }/*if*/
  247.                 break;}
  248.  
  249.                 case '#': {
  250.                     if ( isxdigit( line[index+1] ) ) {
  251. /* gobble up hex digits */
  252.                         index++;
  253.                         while ( isxdigit(line[index]) ){
  254.                             index++;
  255.                         }/*while*/
  256.  
  257.                         tok = NUMBER;
  258.  
  259.                     } else {
  260.                         tok = line[index++];
  261.  
  262.                     }/*if*/
  263.  
  264.                 break;}
  265.  
  266.                 case '\'': {
  267.                     if ( line[index+1] != '*'
  268.                          && line[index+2] == '\'' ) {
  269.  
  270.                         index+=3;
  271.                         tok = CHCON;
  272.  
  273.                     } else if ( line[index+1] == '*'
  274.                          && line[index+2] != '#' 
  275.                          && line[index+3] == '\'' ) {
  276.  
  277.                         index+=4;
  278.                         tok = CHCON;
  279.  
  280.                     } else if ( line[index+1] == '*'
  281.                          && line[index+2] == '#' 
  282.                          && isxdigit( line[index+3] )
  283.                          && isxdigit( line[index+4] )
  284.                          && line[index+5] == '\'' ) {
  285.  
  286.                         index+=6;
  287.                         tok = CHCON;
  288.  
  289.                     } else {
  290.                         tok = line[index++];
  291.  
  292.                     }/*if*/
  293.  
  294.                 break;}
  295.  
  296.  
  297.                 case '"': {
  298.                     int    lindex=index+1;
  299.  
  300.                     while ( line[lindex] != '"'
  301.                          && lindex <= llen ) {
  302.                         lindex++;
  303.                     }/*while*/
  304.  
  305.                     if ( line[lindex] == '"' ) {
  306.                         index = lindex+1;
  307.                         tok = STR;
  308.  
  309.                     } else {
  310.                         tok = line[index++];
  311.  
  312.                     }/*if*/
  313.  
  314.                 break;}
  315.  
  316. /* do extra look ahead that yacc can not do for CHAN | VAR | VALUE */
  317.                 case ',': {
  318.                     int    lindex=index+1;
  319.  
  320.                     while ( line[lindex] == ' ' ) {
  321.                         lindex++;
  322.                     }/*while*/
  323.  
  324.                     if ( strncmp(&line[lindex], "CHAN", 4)
  325.                          == 0
  326.                        || strncmp(&line[lindex], "VAR", 3)
  327.                          == 0
  328.                        || strncmp(&line[lindex], "VALUE", 5)
  329.                          == 0 ) {
  330.  
  331.                         index++;
  332.                         tok = COMMA;
  333.  
  334.                     } else {
  335.                         tok = line[index++];
  336.  
  337.                     }/*if*/
  338.  
  339.                 break;}
  340.  
  341. /* oh well pass back to yacc & let it cope  - if not digit or alpha */
  342.                 default: {
  343.                     if ( isdigit( line[index] ) ) {
  344. /* gobble up digits */
  345.                         index++;
  346.                         while ( isdigit(line[index]) ){
  347.                             index++;
  348.                         }/*while*/
  349.  
  350.                         tok = NUMBER;
  351.                         break;
  352.  
  353.                     } else if ( isalpha( line[index] ) ) {
  354.                         int    i, wlen = 1;
  355.                         index++;
  356. /* gobble up associated chs */
  357.                         while ( isalpha( line[index] )
  358.                             || isdigit( line[index])
  359.                             || line[index] == '.' ){
  360.                             wlen++;
  361.                             index++;
  362.                         }/*while*/
  363.  
  364. /* now check against reserved word list */
  365.                         for ( i=0;
  366.                              rlist[i].word != NULL;
  367.                             i++ ) {
  368.  
  369.                             if ( rlist[i].len
  370.                                 != wlen ) {
  371.                                 continue;
  372.                             }/*if*/
  373.  
  374.                             if ( strncmp(
  375.                               &line[index-wlen],
  376.                               rlist[i].word,
  377.                               wlen ) == 0 ) {
  378.  
  379.                              tok = rlist[i].tok;
  380.                              break;
  381.                             }/*if*/
  382.                         }/*for*/
  383.  
  384. /* not a reserved word */
  385.                         if ( tok < 0 ) {
  386.                             tok = ID;
  387.                         }/*if*/
  388.                         break;
  389.  
  390.                     }/*if*/
  391.  
  392.                     tok = line[index++];
  393.  
  394.                 break;}/*default*/
  395.  
  396.             }/*switch*/
  397.  
  398.         break;}/*Rest*/
  399.  
  400.         case Eof: {
  401. /* do we have some indentation to adjust for ... */
  402.             if ( curind > 0 ) {
  403.                 curind--;
  404.                 tok = END;
  405.             } else {
  406.                 tok = 0;
  407.             }/*if*/
  408.  
  409.  
  410.         break;}/*Eof*/
  411.  
  412.  
  413.     }/*switch*/
  414.  
  415.     }/*while*/
  416.  
  417. /* return whats required after setting yytext etc */
  418.     if ( index > sind ) {
  419.         int    i;
  420.         yylen = index - sind;
  421.  
  422.         for ( i = 0; i < yylen; i++ ) {
  423.             yytext[i] = line[sind+i];
  424.         }/*for*/
  425.  
  426.         yytext[yylen] = '\0';
  427.  
  428.     } else {
  429.         yylen = 0;
  430.         yytext[0] = '\0';
  431.  
  432.     }/*if*/
  433.  
  434. /* debug report */
  435.     if ( ldebug ) {
  436.         fprintf( stderr, "yylex: token %d <%s>\n", tok, yytext );
  437.     }/*if*/
  438.  
  439.     return( tok );
  440.  
  441. }/*yylex*/
  442.  
  443. /*************************************************************************/
  444.  
  445. m_nulline()
  446. /* return true if a null line */
  447. {
  448.  
  449.     int    lindex=index;    /* local index */
  450.  
  451. /* tramp thru spaces */
  452.     while ( line[lindex] == ' ' ) {
  453.         lindex++;
  454.     }/*while*/
  455.  
  456. /* any comment ? */
  457.     if ( line[lindex] == '-' && line[lindex+1] == '-' ) {
  458.         yylineno++;
  459.         return( TRUE );
  460.  
  461. /* or we got to the end of the line */
  462.     } else if ( line[lindex]== '\n' ) {
  463.         yylineno++;
  464.         return( TRUE );
  465.  
  466.     }/*if*/
  467.  
  468.     return( FALSE );
  469.  
  470. }/*m_nulline*/
  471.  
  472. /* end occamlex.c */
  473.